package cn.chencq.moudle.lottery.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;

import cn.chencq.moudle.bp.BPFactory;
import cn.chencq.moudle.lottery.dao.LotteryDao;
import cn.chencq.moudle.lottery.entity.Lottery;
import cn.chencq.moudle.lottery.service.LotteryService;
import cn.chencq.moudle.sys.dao.BaseDao;
import cn.chencq.moudle.sys.service.impl.BaseServiceImpl;
import cn.chencq.page.PageBean;
import cn.chencq.page.PageParam;
import cn.chencq.utils.DateUtils;
import cn.chencq.utils.LotteryApiUtils;
import cn.chencq.utils.MD5Utils;
import cn.chencq.utils.redis.RedisKey;
import cn.chencq.utils.redis.RedisUtils;

@Service
public class LotteryServiceImpl extends BaseServiceImpl<Lottery> implements LotteryService {

	private static final Logger logger = LoggerFactory.getLogger(LotteryServiceImpl.class);
	@Autowired
	private LotteryDao lotteryDao;

	@Override
	protected BaseDao getBaseDao() {
		return this.lotteryDao;
	}

	@Override
	public PageBean<Lottery> listPage(PageParam pageParam) {
		PageHelper.orderBy(" lottery_id desc");
		return super.listPage(pageParam);
	}

	@Override
	public void save(Lottery t) {
		t.setId(getId(t));
		lotteryDao.save(t);
	}

	@Override
	public void batchSaveOrUpdate(List<Lottery> list) {
		if (Objects.isNull(list) || list.isEmpty()) {
			return;
		}
		list.stream().forEach(t -> {
			t.setId(getId(t));
		});
		lotteryDao.batchSaveOrUpdate(list);
	}

	private String getId(Lottery l) {
		String ming = l.getLotteryId() + l.getLotteryType() + l.getLotteryDate().getTime();
		return MD5Utils.getMD5Code(ming);
	}

	@Override
	public long syncData(String startTime, String endTime, String lotteryType) {
		long count = 0;
		Date startDate = null;
		Date endDate = null;
		if (!StringUtils.isEmpty(startTime)) {
			startDate = DateUtils.str2Date(startTime, null);
		}

		if (!StringUtils.isEmpty(endTime)) {
			endDate = DateUtils.str2Date(endTime, null);
		}

		int totalPage = LotteryApiUtils.getTotalPage(lotteryType);
		if (Objects.nonNull(startDate) && Objects.nonNull(endDate)) {
			while (startDate.compareTo(endDate) <= 0) {
				String dateStr = DateUtils.date2Str(startDate, null);
				List<Lottery> list = null;
				for (int page = 1; page <= totalPage; page++) {
					list = LotteryApiUtils.getLotteryList(lotteryType, page, dateStr);
					count += (null != list ? list.size() : 0);
					batchSaveOrUpdate(list);
					logger.info("时间:{} ,第:{}页,获取到:{}条", dateStr, page, (null != list ? list.size() : 0));
				}
				startDate = DateUtils.addDay(startDate, 1);
			}
		} else {
			String dateStr = startTime;
			if (Objects.isNull(dateStr)) {
				dateStr = DateUtils.date2Str(new Date(), null);
			}
			for (int page = 1; page <= totalPage; page++) {
				List<Lottery> list = LotteryApiUtils.getLotteryList(lotteryType, page, dateStr);
				count += (null != list ? list.size() : 0);
				batchSaveOrUpdate(list);
				logger.info("时间:{} ,第:{}页,获取到:{}条", dateStr, page, (null != list ? list.size() : 0));
			}
		}
		return count;
	}

	@Override
	public List<Lottery> queryByDate(String lotteryDate, String lotteryType) {
		return lotteryDao.queryByDate(lotteryDate, lotteryType);
	}

	@Override
	public JSONObject predict(String lotteryType, String lotteryId) {
		// 查询原始数据
		List<Lottery> lotterys = lotteryDao.queryLastTen(DateUtils.date2Str(new Date(), null), lotteryType);

		// 数据清洗处理
		List<double[]> list = new ArrayList<double[]>();
		for (Lottery lottery : lotterys) {
			double[] res = formateLotteryNumbers(lottery.getLotteryNumbers());
			list.add(res);
		}

		// 训练数据准备
		int row = list.size();
		double[][] trainData = new double[row - 1][];
		double[][] targetData = new double[row - 1][];
		for (int i = 0; i < row; i++) {
			if (i == 0) {
				trainData[0] = list.get(0);
			} else if (i == (row - 1)) {
				targetData[i - 1] = list.get(i);
			} else {
				trainData[i] = list.get(i);
				targetData[i - 1] = list.get(i);
			}
		}

		int[] res = this.getPredictNumber(trainData, targetData);

		// 预测结果输出
		JSONObject json = new JSONObject();
		String lastLotteryId = lotterys.get(row - 1).getLotteryId();
		json.put("lotteryId", Long.valueOf(lastLotteryId) + 1);
		json.put("lotteryNumbers", res);
		json.put("lotteryType", lotteryType);

		return json;
	}

	@Override
	public int[] getPredictNumber(double[][] trainData, double[][] targetData) {
		int[] res = new int[3];
		BPFactory.initialization(3, 10, 3);

		// 开始循环学习
		int row = trainData.length;
		for (int i = 0; i < 1000; i++) { // 循环学习
			for (int j = 0; j < row; j++) {
				BPFactory.train(trainData[j], targetData[j]);
			}
		}

		// 进行预测
		double[] test = targetData[row - 1]; // 当前最新一期数据
		double[] result = BPFactory.test(test, 2);

		// 结果处理
		for (int i = 0; i < result.length; i++) {
			res[i] = new Double(result[i] * 100).intValue();
		}
		return res;
	}

	private double[] formateLotteryNumbers(String lotteryNumbers) {
		String[] array = lotteryNumbers.split(",");
		double[] d = new double[3];
		for (int i = 0; i < array.length; i++) {
			d[i] = Double.valueOf(array[i]) / 100.00;
		}
		return d;
	}

}
